package com.xyzwps.reactor;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.Duration;

public class Ex04ErrorHandling {

    public static void main(String[] args) throws IOException {

        System.out.println("选择 demo：");
        var reader = new BufferedReader(new InputStreamReader(System.in));
        switch (reader.readLine()) {
            case "return" -> demoOnErrorReturn();
            case "resume" -> demoOnErrorResume();
            case "continue" -> demoOnErrorContinue();
            case "retry" -> demoRetry();
            default -> System.out.println("啥也没选");
        }
    }

    /**
     * onErrorReturn: 发生错误时找个替代，错误被吞掉。注意，订阅提前结束，原因是任何错误都会发送一个终结事件
     */
    static void demoOnErrorReturn() {
        Flux.just(3, 2, 1, 0, -1)
                .map(i -> 6 / i)
                .onErrorReturn(100000)
                .subscribe(
                        System.out::println,
                        t -> System.out.println("Final error:  " + t.getMessage())
                );
    }

    /**
     *
     */
    static void demoOnErrorContinue() {
        Flux.just(3, 2, 1, 0, -1)
                .map(i -> 6 / i)
                .onErrorContinue((t, o) -> {
                    System.out.println("object: " + o);
                    System.out.println("error : " + t);
                })
                .subscribe(
                        System.out::println,
                        t -> System.out.println("Final error:  " + t)
                );
    }

    /**
     * 和 onErrorReturn 类似，换成一个 publisher 来处理
     */
    static void demoOnErrorResume() {
        Flux.just(3, 2, 1, 0, -1)
                .map(i -> 6 / i)
                .onErrorResume((t) -> {
                    System.out.println("error : " + t);
                    return Mono.just(100000);
                })
                .subscribe(
                        System.out::println,
                        t -> System.out.println("Final error:  " + t)
                );
    }

    static void demoRetry() {
        Flux.interval(Duration.ofMillis(250))
                .map(input -> {
                    if (input < 3) return "tick " + input;
                    throw new RuntimeException("boom");
                })
                .retry(1)
                .elapsed()
                .subscribe(System.out::println, System.err::println);

        try {
            Thread.sleep(2100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
